﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace TD.Interface
{
    abstract class MenuBase : DrawableGameComponent
    {
        /// <summary>
        /// The key that is used to switch back to the previous menu.
        /// </summary>
        private const Keys BACK = Keys.Back;

        protected SpriteBatch spriteBatch;
        protected SpriteFont font;
        protected SpriteFont subFont;

        private List<DrawableGameComponent> items;

        public event OnExit Exit;
        public delegate void OnExit(object sender);

        public MenuBase(Game1 game) :
            base(game)
        {
            base.Enabled = false;
            base.Visible = false;
            base.DrawOrder = 0x08100000;
        }

        public override void Initialize()
        {
            // Ensure the menus handle these.
            base.EnabledChanged += new EventHandler<EventArgs>(DelegateEnabledChanged);
            base.VisibleChanged += new EventHandler<EventArgs>(DelegateVisibleChanged);
            
            base.Initialize();
        }
        private void DelegateEnabledChanged(object sender, EventArgs e)
        {
            for (int i = 0; i < items.Count; i++)
            {
                items[i].Enabled = Enabled;
            }

            HandleEnabledChanged(sender, e);
        }
        private void DelegateVisibleChanged(object sender, EventArgs e)
        {
            for (int i = 0; i < items.Count; i++)
            {
                items[i].Visible = Visible;
            }

            HandleVisibleChanged(sender, e);
        }

        protected abstract void HandleEnabledChanged(object sender, EventArgs e);
        protected abstract void HandleVisibleChanged(object sender, EventArgs e);

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // Load the fonts used by the menus.
            font = Game.Content.Load<SpriteFont>("interface/MenuFont");
            subFont = Game.Content.Load<SpriteFont>("interface/MenuSubFont");

            // Add the items.
            items = AddItems();
            foreach (DrawableGameComponent item in items)
            {
                if (item != null)
                {
                    base.Game.Components.Add(item);
                    item.Enabled = this.Enabled;
                    item.Visible = this.Visible;
                }
            }

            base.LoadContent();
        }
        protected abstract List<DrawableGameComponent> AddItems();

        public override void Update(GameTime gameTime)
        {
            if (base.Visible)
            {
                if (((Game1)Game).InputManager.IsKeyPressed(BACK))
                {
                    ExitMenu();
                }
            }
            
            // Give the menu a chance to update the items.
            UpdateItems(items, gameTime);

            base.Update(gameTime);
        }
        protected abstract void UpdateItems(List<DrawableGameComponent> items, GameTime gameTime);

        protected void ExitMenu()
        {
            if (Exit != null)
            {
                Enabled = false;
                Visible = false;
                Exit(this);
            }
        }
    }
}
